import type { TableColumn } from '../../../../../../components/table/types'
import type {
  ComponentStyleIdType,
  EChartsTypes,
} from '../../../../../../types/interfaces'
import type {
  FeedbackTagType,
  GreasyForkIdItem,
  GreasyForkScriptUserType,
  GreasyForkStats,
  GreasyForkStatsItem,
  GreasyForkStorageCategory,
  ResolutionStatusType,
  ScriptFeedbackActionType,
  ScriptStatusActionType,
} from '../../../../../../user_center/tab/personalization/custom_css/theme/others/greasy_fork/module/storage_process/types'
import { BarChart } from '../../../../../../components/bar_chart'
import { CollapsiblePanel } from '../../../../../../components/collapsible_panel'
import { PieChart } from '../../../../../../components/pie_chart'
import { Table } from '../../../../../../components/table'
import { BaseModule } from '../../../../../../lib/abstract'
import { PageHandler } from '../../../../../../lib/page_handler'
import { ToolKit } from '../../../../../../lib/utils/toolkit'
import {
  BodyClasses,
  BUTTON_STYLES,
  ComponentStyleId,
  getChartLabelColor,
  logger,
  themeClassPrefix,
  TITLE_STYLES,
} from '../../../../../../types/constants'
import { GREASY_FORK_BASE_URL } from '../../../../../../types/constants/web_link'
import { SYMBOLS } from '../../../../../../types/interfaces'
import { UpdateOperation } from '../../../../../../user_center/tab/personalization/custom_css/theme/others/greasy_fork/module/storage_process/types'
import { USER_TAG_LABELS } from '../../../../../../user_center/tab/personalization/custom_css/theme/others/greasy_fork/page/lib/types'
import { ConfigManager } from '../../../../../config_manager'
import { StyleManager } from '../../../../../style_manager'
import { FEEDBACK_TAG_LABELS } from '../../../../interaction/platform/greasy_fork/feedback_mark'
import { SCRIPT_TAG_LABELS } from '../../../../interaction/platform/greasy_fork/script_mark'
import { styles } from './styles'

// 图表ID
const CHART_IDS = {
  USER_TYPES: 'user-types-chart',
  SCRIPT_STATS: 'script-stats-chart',
  FEEDBACK_TAGS: 'feedback-tags-chart',
  FEEDBACK_STATUS: 'script-status-chart',
}

// 表格ID
const TABLE_IDS = {
  USER_TYPES: 'user-types-table',
  SCRIPT_LINKER: 'script-liker-table',
  SCRIPT_STATUS: 'script-status-table',
  FEEDBACK_TAGS: 'feedback-tags-table',
  FEEDBACK_STATUS: 'feedback-status-table',
}

// 表格类型列名称配置
const TABLE_TYPE_COLUMN_NAMES = {
  [TABLE_IDS.USER_TYPES]: '用户类型',
  [TABLE_IDS.SCRIPT_LINKER]: '是否喜欢',
  [TABLE_IDS.SCRIPT_STATUS]: '运行状态',
  [TABLE_IDS.FEEDBACK_TAGS]: '内容类型',
  [TABLE_IDS.FEEDBACK_STATUS]: '处理进度',
}

// 反馈类型前缀
export enum SCRIPT_TYPE_PREFIX {
  TAGS = '[反馈]',
  STATUS = '[状态]',
}

export interface Config {
  enabled?: boolean
  showUserTypes?: boolean
  showScript?: boolean
  showFeedback?: boolean
  showLinks?: boolean
  compactMode?: boolean
}

export class GreasyForkStatsPanel extends BaseModule {
  readonly id: string = 'greasy_fork_stats_panel'
  readonly styleId: string = ComponentStyleId[this.name]
  isInitialized: boolean = false
  readonly supportedPlatforms: string[] = ConfigManager.getInstance().moduleSupportedPlatforms(this.name)
  private static instance: GreasyForkStatsPanel
  private pageHandler: PageHandler = PageHandler.getInstance()
  private statsPanel: CollapsiblePanel | null = null
  private charts: Map<string, EChartsTypes> = new Map()
  private tables: Map<string, Table> = new Map()
  private readonly titleClass = `${TITLE_STYLES.SECONDARY.className} ${themeClassPrefix}-dark ${BodyClasses.NO_DECORATION}`

  config: Config = {
    enabled: true,
    showUserTypes: true,
    showScript: true,
    showFeedback: true,
    showLinks: true,
    compactMode: false,
  }

  get name(): ComponentStyleIdType {
    return 'GreasyForkStatsPanel'
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): GreasyForkStatsPanel {
    if (!GreasyForkStatsPanel.instance) {
      GreasyForkStatsPanel.instance = new GreasyForkStatsPanel()
    }
    return GreasyForkStatsPanel.instance
  }

  destroy(): void {
    try {
      // 1. 移除所有添加的统计面板元素
      $('.gf-stats-panel-container').remove()

      // 2.销毁所有图表
      this.charts.forEach(chart => chart.destroy())
      this.charts.clear()

      // 3. 销毁所有表格
      this.tables.forEach(table => table.destroy())
      this.tables.clear()

      // 4. 标记状态
      this.isInitialized = false

      super.destroy()
    }
    catch (error: any) {
      logger.error(`[${this.name}] Error occurred during module destruction:`, error)
    }
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.renderStatsPanel()

    // 注册样式
    StyleManager.getInstance().registerStyle(this.styleId, this.getStyles(), false, true)
  }

  onToggleCallback(_id: string, checked: boolean): void {
    super.onToggleCallback(_id, checked)
  }

  private renderStatsPanel(): void {
    // 获取统计数据
    const statsData: GreasyForkStats = this.pageHandler.storages.greasyFork.getAll()

    if (!statsData || Object.keys(statsData).length === 0) {
      logger.warn(`[${this.name}] No stats data found`)
      return
    }

    // 确定插入位置
    const $container = this.getInsertContainer()
    if (!$container || !$container.length) {
      logger.warn(`[${this.name}] Could not find container for stats panel`)
      return
    }

    // 渲染面板
    this.initStatsPanel(statsData)

    if (!this.statsPanel)
      return

    $container.prepend(this.statsPanel.render())
    this.statsPanel.mount($container)

    // 在面板渲染后初始化图表
    setTimeout(() => {
      this.initBarChart(statsData)
      this.initPieChart(statsData)
      this.initTables(statsData)
      this.bindEvents()
    }, 100)

    logger.info(`[${this.name}] Stats panel rendered`)
  }

  /**
   * 绑定事件
   */
  private bindEvents(): void {
    this.handleClickRefreshButton()
    this.handleClickClearCacheButton()
    this.handleClickRemoveMarkButtons()
  }

  /**
   * 防抖处理，避免异常高频触发
   */
  private debounceRefresh = ToolKit.func.debounce(async () => {
    await this.refreshData()
  }, 500)

  private getInsertContainer(): JQuery<HTMLElement> {
    return $('#script-content')
  }

  /**
   * 初始化所有表格
   */
  private initTables(statsData: GreasyForkStats): void {
    if (this.config.showUserTypes) {
      this.createUserTypesTable(statsData)
    }
    if (this.config.showScript) {
      this.createScriptTables(statsData)
    }
    if (this.config.showFeedback) {
      this.createFeedbackTables(statsData)
    }
  }

  // 初始化表格
  private initTable($container: JQuery, table: Table) {
    $container.html(table.render())
    table.mount($container)
    this.tables.set(table.props.id, table)
  }

  /**
   * 初始化用户类型图表
   */
  private initBarChart(statsData: any): void {
    // 合并脚本数据（保持各自独立）
    const combinedScriptData = this.combineScriptData(
      statsData.script.liker,
      statsData.script.status,
    )

    const BAR_CHARTS_CONFIG = [
      {
        id: CHART_IDS.USER_TYPES,
        categories: Object.entries(statsData.user.types).map(([type, { count, lastUpdated }]: [string, any]) => {
          return this.getUserTypeLabel(type, count, lastUpdated)
        }),
        values: Object.values<GreasyForkStatsItem>(statsData.user.types).map(item => item.count || 0),
        seriesOptions: {
          itemStyle: {
            color: (params: any) => {
              // 从格式化后的标签中提取原始类型
              const match = params.name.match(/^(\S+)\s(.+)(?:\n|$)/)
              const iconPart: string = (match?.[1] || '').trim()
              const labelPart: string = (match?.[2] || '').trim()

              // 查找匹配项
              const labelItem = Object.values(USER_TAG_LABELS).find(item =>
                item.icon === iconPart && item.label === labelPart,
              )

              return getChartLabelColor(labelItem?.bgColor || '#5470C6')
            },
          },
        },
      },
      {
        id: CHART_IDS.SCRIPT_STATS,
        categories: Object.entries(combinedScriptData).map(([key, { count, lastUpdated, type }]: [string, any]) => {
          return this.getScriptLabel(key, type, count, lastUpdated)
        }),
        values: Object.values<GreasyForkStatsItem>(combinedScriptData).map(item => item.count || 0),
        seriesOptions: {
          itemStyle: {
            color: (params: any) => {
              // 从格式化后的标签中提取原始类型
              const cleanName = params.name.replace(/\[(?:反馈|状态)\]/, '')
              const match = cleanName.match(/^(\S+)\s(.+)(?:\n|$)/)
              const iconPart: string = (match?.[1] || '').trim()
              const labelPart: string = (match?.[2] || '').trim()

              // 查找匹配项
              const labelItem = Object.values(SCRIPT_TAG_LABELS).find(item =>
                item.icon === iconPart && item.label === labelPart,
              )

              return getChartLabelColor(labelItem?.bgColor || '#5470C6')
            },
          },
        },
      },
    ]

    // 批量初始化图表
    BAR_CHARTS_CONFIG.forEach((config) => {
      const { id, categories, values } = config
      // 创建并初始化图表
      const barChart = new BarChart({
        id,
        categories,
        values,
        seriesOptions: config.seriesOptions,
        onClick: (params: ChartClickParams, _event) => {
          if (params.chartId === CHART_IDS.USER_TYPES) {
            this.tables.get(TABLE_IDS.USER_TYPES)?.setSearchColumn('type')
            const cleanedText = params.name.split('\n')[0].trim()
            this.tables.get(TABLE_IDS.USER_TYPES)?.setSearchText(cleanedText)
          }
          else if (params.chartId === CHART_IDS.SCRIPT_STATS) {
            if (params.name.includes(SCRIPT_TYPE_PREFIX.TAGS)) {
              this.tables.get(TABLE_IDS.SCRIPT_LINKER)?.setSearchColumn('type')
              const cleanedText = params.name.replace(SCRIPT_TYPE_PREFIX.TAGS, '').split('\n')[0].trim()
              this.tables.get(TABLE_IDS.SCRIPT_LINKER)?.setSearchText(cleanedText)
            }
            else if (params.name.includes(SCRIPT_TYPE_PREFIX.STATUS)) {
              this.tables.get(TABLE_IDS.SCRIPT_STATUS)?.setSearchColumn('type')
              const cleanedText = params.name.replace(SCRIPT_TYPE_PREFIX.STATUS, '').split('\n')[0].trim()
              this.tables.get(TABLE_IDS.SCRIPT_STATUS)?.setSearchText(cleanedText)
            }
          }
        },
      })

      // 渲染图表
      $(`#${id}`).replaceWith(barChart.render())
      barChart.bindEvents()
      this.charts.set(id, barChart)
    })
  }

  /**
   * 获取用户类型标签
   */
  getUserTypeLabel(type: any, count: any, lastUpdated: any): string {
    const labelPart = USER_TAG_LABELS[type as GreasyForkScriptUserType]?.label || type
    const iconPart = USER_TAG_LABELS[type as GreasyForkScriptUserType]?.icon || ''

    if (count === 0) {
      return `${iconPart} ${labelPart}`
    }
    else {
      return `${iconPart} ${labelPart}\n(${this.formatTime(lastUpdated)})`
    }
  }

  getScriptLabel(key: any, type: any, count: any, lastUpdated: any): string {
    // 根据类型选择正确的标签
    const originalKey = key.replace(/^(liker|status)_/, '')
    const labelKey = type === 'liker'
      ? SCRIPT_TAG_LABELS[originalKey as ScriptFeedbackActionType]
      : SCRIPT_TAG_LABELS[originalKey as ScriptStatusActionType]

    const labelPart = labelKey?.label || originalKey
    const iconPart = labelKey?.icon || ''
    const typePrefix = type === 'liker' ? `${SCRIPT_TYPE_PREFIX.TAGS} ` : `${SCRIPT_TYPE_PREFIX.STATUS} `

    return count === 0
      ? `${iconPart} ${typePrefix}${labelPart}`
      : `${iconPart} ${typePrefix}${labelPart}\n(${this.formatTime(lastUpdated)})`
  }

  /**
   * 合并脚本点赞和状态数据（保持各自独立）
   */
  private combineScriptData(likerData: any, statusData: any): any {
  // 创建一个新合并对象
    const combined: any = {}

    // 添加点赞数据
    Object.keys(likerData).forEach((key) => {
      combined[`liker_${key}`] = {
        ...likerData[key],
        type: 'liker', // 标记为点赞数据
      }
    })

    // 添加状态数据
    Object.keys(statusData).forEach((key) => {
      combined[`status_${key}`] = {
        ...statusData[key],
        type: 'status', // 标记为状态数据
      }
    })

    return combined
  }

  private initPieChart(statsData: any): void {
    const PIE_CHARTS_CONFIG = [
      {
        id: CHART_IDS.FEEDBACK_TAGS,
        title: '内容类型分布',
        width: '50%',
        data: Object.entries(statsData.feedback.tags).map(([tag, item]: [string, any]) => ({
          name: FEEDBACK_TAG_LABELS[tag as FeedbackTagType]?.label || tag,
          value: item.count,
        })),
        seriesOptions: {
          itemStyle: {
            color: (params: any) => {
              const labelItem = Object.values(FEEDBACK_TAG_LABELS).find(item => item.label === params.name)
              return getChartLabelColor(labelItem?.bgColor || '#5470C6', params.name)
            },
          },
        },
      },
      {
        id: CHART_IDS.FEEDBACK_STATUS,
        title: '处理进度分布',
        width: '50%',
        data: Object.entries(statsData.feedback.status).map(([status, item]: [string, any]) => ({
          name: FEEDBACK_TAG_LABELS[status as ResolutionStatusType]?.label || status,
          value: item.count,
        })),
        seriesOptions: {
          itemStyle: {
            color: (params: any) => {
              const labelItem = Object.values(FEEDBACK_TAG_LABELS).find(item => item.label === params.name)
              return getChartLabelColor(labelItem?.bgColor || '#5470C6', params.name)
            },
          },
        },
      },
    ]

    // 批量初始化饼图
    PIE_CHARTS_CONFIG.forEach((config) => {
      const pieChart = new PieChart({
        id: config.id,
        data: config.data,
        title: config.title,
        width: config.width,
        seriesOptions: config.seriesOptions,
        onClick: (params: ChartClickParams, _event) => {
          if (params.chartId === CHART_IDS.FEEDBACK_TAGS) {
            this.tables.get(TABLE_IDS.FEEDBACK_TAGS)?.setSearchColumn('type')
            this.tables.get(TABLE_IDS.FEEDBACK_TAGS)?.setSearchText(params.name)
          }
          else if (params.chartId === CHART_IDS.FEEDBACK_STATUS) {
            this.tables.get(TABLE_IDS.FEEDBACK_STATUS)?.setSearchColumn('type')
            this.tables.get(TABLE_IDS.FEEDBACK_STATUS)?.setSearchText(params.name)
          }
        },
      })

      // 渲染图表
      $(`#${config.id}`).replaceWith(pieChart.render())
      pieChart.bindEvents()
      this.charts.set(config.id, pieChart)
    })
  }

  private initStatsPanel(data: any): void {
    const {
      showUserTypes,
      showScript,
      showFeedback,
      compactMode,
    } = this.config

    const htmlTemplate = `
      <div class="gf-stats-panel ${compactMode ? 'compact' : ''}">
        ${this.createActionsButton()}
        ${showFeedback ? this.createFeedbackHTML() : ''}
        ${showScript ? this.createScriptHTML() : ''}
        ${showUserTypes ? this.createUserTypesHTML() : ''}
      </div>
    `

    this.statsPanel = new CollapsiblePanel({
      id: 'gf-stats-info',
      className: 'gf-stats-panel-container',
      type: 'note',
      title: 'Greasy Fork 标记数据',
      content: htmlTemplate,
      collapsible: true,
      timeContent: data.lastUpdateTime ? `最后更新时间: ${this.formatTime(data.lastUpdateTime)}` : '',
    })
  }

  /**
   * 创建清除按钮
   */
  private createActionsButton(): string {
    return `
      <div class="stats-action-buttons">
        <button class="btn ${BUTTON_STYLES.danger.className} gf-clear-cache-btn">
          <span class="gf-icon-clear"></span> 清空标记
        </button>
        <button class="btn ${BUTTON_STYLES.secondary.className} gf-refresh-btn">
          <span class="gf-icon-refresh"></span> 刷新数据
        </button>
      </div>
    `
  }

  /**
   * 创建操作按钮
   * @param id 项目ID
   * @param category 存储分类
   * @param type 标记类型
   */
  private createActionButton(id: string, category: GreasyForkStorageCategory, type: string): string {
    return `
      <button class="gf-remove-mark-btn" 
        data-id="${id}" 
        data-category="${category}" 
        data-type="${type}">
        取消标记
      </button>
    `
  }

  /**
   * 处理刷新按钮点击事件
   */
  private handleClickRefreshButton(): void {
    $('.gf-refresh-btn').on('click', this.debounceRefresh)
  }

  /**
   * 处理清除缓存按钮点击事件
   */
  private handleClickClearCacheButton(): void {
    $('.gf-clear-cache-btn').on('click', this.clearFeedbackCache.bind(this))
  }

  /**
   * 处理取消标记按钮点击事件（使用事件委托）
   */
  private handleClickRemoveMarkButtons(): void {
    $(document).on('click', '.gf-remove-mark-btn', async (event) => {
      const $button = $(event.currentTarget)
      const id = $button.data('id')
      const category = $button.data('category')
      const type = $button.data('type')

      try {
        // 确认操作
        const { isConfirmed } = await this.pageHandler.ui.toast.confirm({
          title: '取消标记',
          html: `${SYMBOLS.STATUS.WARNING} 确定要取消此标记吗？<br><small>（ID: ${id}）</small>`,
          icon: 'warning',
        })

        if (isConfirmed) {
          // 执行取消标记操作
          this.pageHandler.storages.greasyFork.updateStorageItem(
            category,
            type,
            id,
            UpdateOperation.Remove,
          )

          // 获取当前表格
          const tableId = $button.closest('table').attr('id')

          if (!tableId)
            return

          const table = this.tables.get(tableId)
          // 重新获取数据并更新表格数据
          const statsData = this.pageHandler.storages.greasyFork.getAll()
          const updatedData = this.getTableData(category, statsData)
          table?.updateData(updatedData)
        }
      }
      catch (error: any) {
        logger.error(`[${this.name}] 取消标记失败:`, error)
        await this.pageHandler.ui.toast.alert({
          title: '操作失败',
          text: `取消标记时出错\n${error.message}`,
          icon: 'error',
        })
      }
    })
  }

  /**
   * 获取表格数据
   * @param category 存储分类
   * @param statsData 统计数据
   * @returns 表格数据
   */
  private getTableData(category: GreasyForkStorageCategory, statsData: GreasyForkStats): any[] {
    switch (category) {
      case 'user.types':
        return Object.entries(statsData.user.types)
          .filter(([_, { count }]: [string, any]) => count !== 0)
          .flatMap(([type, { ids }]: [string, any]) =>
            ids.map((item: GreasyForkIdItem) => ({
              id: item.id,
              name: this.pageHandler.storages.greasyFork.getUserName(item.id),
              type,
              icon: USER_TAG_LABELS[type as GreasyForkScriptUserType]?.icon || '',
              label: USER_TAG_LABELS[type as GreasyForkScriptUserType]?.label || type,
              createdTime: this.formatTime(item.lastUpdated),
            })),
          )

      case 'script.liker':
      case 'script.status':
      { const source = category === 'script.liker'
        ? statsData.script.liker
        : statsData.script.status

      return Object.entries(source)
        .filter(([_, { count }]) => count !== 0)
        .flatMap(([status, { ids }]) =>
          ids.map(item => ({
            id: item.id,
            name: this.pageHandler.storages.greasyFork.getScriptName(item.id),
            type: status,
            icon: SCRIPT_TAG_LABELS[status as ScriptFeedbackActionType | ScriptStatusActionType]?.icon || '',
            label: SCRIPT_TAG_LABELS[status as ScriptFeedbackActionType | ScriptStatusActionType]?.label || status,
            createdTime: this.formatTime(item.lastUpdated),
          })),
        ) }

      case 'feedback.tags':
      case 'feedback.status':
      { const feedbackSource = category === 'feedback.tags'
        ? statsData.feedback.tags
        : statsData.feedback.status

      return Object.entries(feedbackSource)
        .filter(([_, { count }]) => count !== 0)
        .flatMap(([tag, { ids }]) =>
          ids.map(item => ({
            id: item.id,
            name: this.pageHandler.storages.greasyFork.getScriptName(item.id.split('#')[0]),
            description: this.pageHandler.storages.greasyFork.getFeedbackDescription(item.id),
            type: tag,
            icon: FEEDBACK_TAG_LABELS[tag as FeedbackTagType | ResolutionStatusType]?.icon || '',
            label: FEEDBACK_TAG_LABELS[tag as FeedbackTagType | ResolutionStatusType]?.label || tag,
            createdTime: this.formatTime(item.lastUpdated),
          })),
        ) }

      default:
        return []
    }
  }

  /**
   * 刷新数据
   */
  private async refreshData(): Promise<void> {
    try {
      // 显示加载状态
      $('.gf-refresh-btn').prop('disabled', true).html(`
          <span class="gf-loading-spinner"></span> 刷新中...
        `)

      // 重新加载数据
      await this.loadData()
    }
    catch (error: any) {
      logger.error(`[${this.name}] 刷新数据失败:`, error)
      await this.pageHandler.ui.toast.alert({
        title: '刷新失败',
        text: `刷新数据时出错\n${error.message}`,
        icon: 'error',
      })
    }
    finally {
      // 恢复按钮状态
      $('.gf-refresh-btn').prop('disabled', false).html(`
          <span class="gf-icon-refresh"></span> 刷新数据
        `)
    }
  }

  /**
   * 刷新数据并重新渲染面板
   */
  private async loadData(): Promise<void> {
    // 1. 销毁现有组件
    this.charts.forEach(chart => chart.destroy())
    this.charts.clear()
    this.tables.forEach(table => table.destroy())
    this.tables.clear()
    this.statsPanel = null

    // 2. 重新获取数据
    const statsData = this.pageHandler.storages.greasyFork.getAll()

    // 3. 更新最后更新时间
    this.updatePanelLastUpdateTime(statsData.lastUpdateTime)

    // 4. 重新渲染面板
    setTimeout(() => {
      this.initBarChart(statsData)
      this.initPieChart(statsData)
      this.initTables(statsData)
      this.bindEvents()
    }, 100)
  }

  /**
   * 更新面板最后更新时间
   * @param lastUpdateTime 最后更新时间
   */
  private updatePanelLastUpdateTime(lastUpdateTime: number) {
    $('.gf-stats-panel-container .panel-time').text(`最后更新时间：${this.formatTime(lastUpdateTime)}`)
  }

  /**
   * 清空反馈标记缓存
   */
  private async clearFeedbackCache(): Promise<void> {
    try {
      const { isConfirmed } = await this.pageHandler.ui.toast.confirm({
        title: '清空油猴标记',
        html: `
        <div>
          ${SYMBOLS.STATUS.WARNING} 确定要清空所有标记缓存吗？
        </div>
        <small>
          （将清除所有用户类型、脚本标记和反馈标记数据，此操作不可撤销！！！）
        </small>
      `,
        icon: 'warning',
        customClass: {
          confirmButton: 'btn btn-danger',
        },
      })
      if (isConfirmed) {
        this.pageHandler.storages.greasyFork.clear()
        ToolKit.ui.page.refreshPage()
      }
    }
    catch (error: any) {
      logger.error(`[${this.name}] 清空标记失败:`, error)
      await this.pageHandler.ui.toast.alert({
        title: '操作失败',
        text: `清空标记时出错\n${error.message}`,
        icon: 'error',
      })
    }
  }

  private createUserTypesHTML(): string {
    return `
      <div class="stats-section">
        <h3 class="${this.titleClass}">用户类型</h3>
        <div id="${CHART_IDS.USER_TYPES}"></div>
        <div id="${TABLE_IDS.USER_TYPES}"></div>
      </div>
    `
  }

  private createUserTypesTable(statsData: any): void {
    const columns: TableColumn[] = [
      {
        key: 'id',
        title: '用户id',
        render: (_, row) => this.config.showLinks
          ? this.createLinksHTML(row.id, 'user', row.id)
          : `${row.id}`,
      },
      {
        key: 'name',
        title: '用户名称',
        render: (_, row) => `${row.name}`,
      },
      {
        key: 'type',
        title: TABLE_TYPE_COLUMN_NAMES[TABLE_IDS.USER_TYPES],
        render: (_, row) => `
          <span class="stats-icon">${row.icon}</span>
          ${row.label}
        `,
        searchFn: (_value: string, row: any, keyword: string) => {
          return this.matchRowTypeKeyword(row, keyword)
        },
      },
      {
        key: 'createdTime',
        title: '最新标记时间',
        width: '140px',
        render: (_, row) => `${row.createdTime}`,
      },
      {
        key: 'actions',
        title: '相关操作',
        width: '70px',
        render: (_, row) => this.createActionButton(row.id, 'user.types', row.type),
      },
    ]

    const data = this.getTableData('user.types', statsData)
    const table = new Table({
      id: TABLE_IDS.USER_TYPES,
      columns,
      data,
      showSearch: true,
    })

    Object.keys(data).length > 0 && this.initTable($(`#${TABLE_IDS.USER_TYPES}`), table)
  }

  private createScriptHTML(): string {
    return `
      <div class="stats-section">
        <h3 class="${this.titleClass}">脚本页面</h3>
        <div id="${CHART_IDS.SCRIPT_STATS}"></div>
        <div class="stats-subsection">
          <div id="${TABLE_IDS.SCRIPT_LINKER}"></div>
        </div>
        <div class="stats-subsection">
          <div id="${TABLE_IDS.SCRIPT_STATUS}"></div>
        </div>
      </div>
    `
  }

  private createScriptTables(statsData: any): void {
    const likeColumns: TableColumn[] = [
      {
        key: 'id',
        title: '脚本id',
        width: '70px',
        render: (_, row) => this.config.showLinks
          ? this.createLinksHTML(row.id, 'script', row.id)
          : `${row.id}`,
      },
      {
        key: 'name',
        title: '脚本名称',
        render: (_, row) => `${row.name}`,
      },
      {
        key: 'type',
        title: TABLE_TYPE_COLUMN_NAMES[TABLE_IDS.SCRIPT_LINKER],
        width: '70px',
        render: (_, row) => `
          <span class="stats-icon">${row.icon}</span>
          ${row.label}
        `,
        searchFn: (_value: string, row: any, keyword: string) => {
          return this.matchRowTypeKeyword(row, keyword)
        },
      },
      {
        key: 'createdTime',
        title: '最新标记时间',
        width: '140px',
        render: (_, row) => `${row.createdTime}`,
      },
      {
        key: 'actions',
        title: '相关操作',
        width: '70px',
        render: (_, row) => this.createActionButton(row.id, 'script.liker', row.type),
      },
    ]

    const statusColumns: TableColumn[] = [
      {
        key: 'id',
        title: '脚本id',
        width: '70px',
        render: (_, row) => this.config.showLinks
          ? this.createLinksHTML(row.id, 'script', row.id)
          : `${row.id}`,
      },
      {
        key: 'name',
        title: '脚本名称',
        render: (_, row) => `${row.name}`,
      },
      {
        key: 'type',
        title: TABLE_TYPE_COLUMN_NAMES[TABLE_IDS.SCRIPT_STATUS],
        width: '70px',
        render: (_, row) => `
          <span class="stats-icon">${row.icon}</span>
          ${row.label}
        `,
        searchFn: (_value: string, row: any, keyword: string) => {
          return this.matchRowTypeKeyword(row, keyword)
        },
      },
      {
        key: 'createdTime',
        title: '最新标记时间',
        width: '140px',
        render: (_, row) => `${row.createdTime}`,
      },
      {
        key: 'actions',
        title: '相关操作',
        width: '70px',
        render: (_, row) => this.createActionButton(row.id, 'script.status', row.type),
      },
    ]

    const likerData = this.getTableData('script.liker', statsData)
    const statusData = this.getTableData('script.status', statsData)

    const likerTable = new Table({
      id: TABLE_IDS.SCRIPT_LINKER,
      columns: likeColumns,
      data: likerData,
      showSearch: true,
    })
    const statusTable = new Table({
      id: TABLE_IDS.SCRIPT_STATUS,
      columns: statusColumns,
      data: statusData,
      showSearch: true,
    })

    Object.keys(likerData).length > 0 && this.initTable($(`#${TABLE_IDS.SCRIPT_LINKER}`), likerTable)
    Object.keys(statusData).length > 0 && this.initTable($(`#${TABLE_IDS.SCRIPT_STATUS}`), statusTable)
  }

  private createFeedbackHTML(): string {
    return `
      <div class="stats-section">
        <h3 class="${this.titleClass}">反馈页面</h3>
        <div class="feedback-stats-charts">
          <div id="${CHART_IDS.FEEDBACK_TAGS}"></div>
          <div id="${CHART_IDS.FEEDBACK_STATUS}"></div>
        </div>
        <div class="stats-subsection">
            <div id="${TABLE_IDS.FEEDBACK_TAGS}"></div>
        </div>
        <div class="stats-subsection">
            <div id="${TABLE_IDS.FEEDBACK_STATUS}"></div>
        </div>
      </div>
    `
  }

  private createFeedbackTables(statsData: any): void {
    const tagColumns: TableColumn[] = [
      {
        key: 'id',
        title: '脚本id',
        width: '70px',
        render: (_, row) => {
          const scriptId = row.id.split('#')[0]
          return this.config.showLinks
            ? this.createLinksHTML(scriptId, 'script', scriptId)
            : `${scriptId}`
        },
      },
      {
        key: 'name',
        title: '脚本名称',
        render: (_, row) => `${row.name}`,
      },
      {
        key: 'feedbackId',
        title: '反馈id',
        render: (_, row) => this.config.showLinks
          ? this.createDiscussionLinksHTML(row.id)
          : `${row.id}`,
        searchFn: (_value: string, row: any, keyword: string) => {
          return row.id.toLowerCase().includes(keyword)
        },
      },
      {
        key: 'description',
        title: '反馈描述',
        render: (_, row) => `${row.description}`,
      },
      {
        key: 'type',
        title: TABLE_TYPE_COLUMN_NAMES[TABLE_IDS.FEEDBACK_TAGS],
        width: '90px',
        render: (_, row) => `
          <span class="stats-icon">${row.icon}</span>
          ${row.label}
        `,
        searchFn: (_value: string, row: any, keyword: string) => {
          return this.matchRowTypeKeyword(row, keyword)
        },
      },
      {
        key: 'createdTime',
        title: '最新标记时间',
        width: '140px',
        render: (_, row) => `${row.createdTime}`,
      },
      {
        key: 'actions',
        title: '相关操作',
        width: '70px',
        render: (_, row) => this.createActionButton(row.id, 'feedback.tags', row.type),
      },
    ]

    const statusColumns: TableColumn[] = [
      {
        key: 'id',
        title: '脚本id',
        width: '70px',
        render: (_, row) => {
          const scriptId = row.id.split('#')[0]
          return this.config.showLinks
            ? this.createLinksHTML(scriptId, 'script', scriptId)
            : `${scriptId}`
        },
      },
      {
        key: 'name',
        title: '脚本名称',
        render: (_, row) => `${row.name}`,
      },
      {
        key: 'feedbackId',
        title: '反馈id',
        render: (_, row) => this.config.showLinks
          ? this.createDiscussionLinksHTML(row.id)
          : `${row.id}`,
        searchFn: (_value: string, row: any, keyword: string) => {
          return row.id.toLowerCase().includes(keyword)
        },
      },
      {
        key: 'description',
        title: '反馈描述',
        render: (_, row) => `${row.description}`,
      },
      {
        key: 'type',
        title: TABLE_TYPE_COLUMN_NAMES[TABLE_IDS.FEEDBACK_STATUS],
        width: '90px',
        render: (_, row) => `
          <span class="stats-icon">${row.icon}</span>
          ${row.label}
        `,
        searchFn: (_value: string, row: any, keyword: string) => {
          return this.matchRowTypeKeyword(row, keyword)
        },
      },
      {
        key: 'createdTime',
        title: '最新标记时间',
        width: '140px',
        render: (_, row) => `${row.createdTime}`,
      },
      {
        key: 'actions',
        title: '相关操作',
        width: '70px',
        render: (_, row) => this.createActionButton(row.id, 'feedback.status', row.type),
      },
    ]

    const tagData = this.getTableData('feedback.tags', statsData)
    const statusData = this.getTableData('feedback.status', statsData)

    const tagTable = new Table({
      id: TABLE_IDS.FEEDBACK_TAGS,
      columns: tagColumns,
      data: tagData,
      showSearch: true,
    })
    const statusTable = new Table({
      id: TABLE_IDS.FEEDBACK_STATUS,
      columns: statusColumns,
      data: statusData,
      showSearch: true,
    })

    Object.keys(tagData).length > 0 && this.initTable($(`#${TABLE_IDS.FEEDBACK_TAGS}`), tagTable)
    Object.keys(statusData).length > 0 && this.initTable($(`#${TABLE_IDS.FEEDBACK_STATUS}`), statusTable)
  }

  private createLinksHTML(id: string, type: 'user' | 'script', content: string): string {
    if (!id || id.length === 0)
      return ''

    return `
      <a href="${GREASY_FORK_BASE_URL}/zh-CN/${type === 'user' ? 'users' : 'scripts'}/${id}" 
        target="_blank" rel="noopener noreferrer">
        ${content}
      </a>
    `
  }

  private createDiscussionLinksHTML(id: string): string {
    if (!id || id.length === 0)
      return ''

    const [scriptId, discussionId] = id.split('#')

    return `
      <a href="${GREASY_FORK_BASE_URL}/zh-CN/scripts/${scriptId}/discussions/${discussionId}" 
        target="_blank" rel="noopener noreferrer">
        ${discussionId}
      </a>
      `
  }

  /**
   * 检查行类型数据是否匹配关键字
   * @param row
   * @param row.icon
   * @param row.label
   * @param keyword 搜索关键字
   * @returns 是否匹配
   */
  matchRowTypeKeyword(row: { icon: string, label: string }, keyword: string): boolean {
    if (!keyword.trim())
      return true

    // 规范化处理
    const normalize = (str: string) => str.toLowerCase().replace(/\s+/g, ' ')
    const normKeyword = normalize(keyword)
    const normIcon = normalize(row.icon)
    const normLabel = normalize(row.label)
    const combined = `${normIcon} ${normLabel}`

    return (
      normLabel.includes(normKeyword)
      || normIcon.includes(normKeyword)
      || combined.includes(normKeyword)
    )
  }

  private formatTime(timestamp: number): string {
    if (!timestamp)
      return '未知时间'

    return new Date(timestamp).toLocaleString()
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)

    this.renderStatsPanel()

    logger.info(`[${this.name}] Config updated and applied`, this.config)
  }

  getStyles(): string {
    return styles()
  }
}
